package com.alipay.rebate.shop.scheduler.orderimport;

import com.alipay.rebate.shop.constants.OrdersConstant;
import com.alipay.rebate.shop.constants.UserIncomeConstant;
import com.alipay.rebate.shop.dao.mapper.*;
import com.alipay.rebate.shop.helper.UserIncomeBuilder;
import com.alipay.rebate.shop.model.*;
import com.alipay.rebate.shop.pojo.dingdanxia.*;
import com.alipay.rebate.shop.utils.DecimalUtil;
import com.alipay.rebate.shop.utils.DingdanxiaUtil;
import com.alipay.rebate.shop.utils.ListUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class MeiTuanOrderImporter {
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserIncomeMapper userIncomeMapper;
    @Resource
    private MeituanOrdersMapper meituanOrdersMapper;
    @Resource
    private UserGradeMapper userGradeMapper;
    @Resource
    private MeituanRefundOrdersMapper meituanRefundOrdersMapper;
    @Resource
    private CommissionLevelSettingsMapper commissionLevelSettingsMapper;
    private Logger logger = LoggerFactory.getLogger(MeiTuanOrderImporter.class);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Transactional
    public void importMeiTuanOrders(Integer startTime, Integer endTime,
                                    String sid, Integer page, Integer pageSize) throws IOException {
        MeiTuanResponse meituanOrders = DingdanxiaUtil.getMeituanOrders(startTime, endTime, sid, page, pageSize);
        List<MeituanOrdersRsp> data = meituanOrders.getData();
        logger.debug("data is : {}",data);
        handleMeiTuanResponse(data);
    }

    private void handleMeiTuanResponse(List<MeituanOrdersRsp> data) throws IOException {
        if (!ListUtil.isEmptyList(data)){
            logger.debug("data is not null");
            for (MeituanOrdersRsp orders : data) {
                String orderid = orders.getOrderid();
                MeiTuanOrderResponse meiTuanOrderResponse = DingdanxiaUtil.getMeituanOrderId(orderid);
                handleMeiTuanOrderResponse(meiTuanOrderResponse);
            }
        }
    }

    private void handleMeiTuanOrderResponse(MeiTuanOrderResponse meiTuanOrderResponse){
        logger.debug("meiTuanOrderResponse is : {}",meiTuanOrderResponse);
        MeiTuanRsp meiTuanRsp = meiTuanOrderResponse.getData();

        List<MeiTuanCoupon> coupon = meiTuanRsp.getCoupon();
        MeiTuanOrderRsp order = meiTuanRsp.getOrder();
        List<MeiTuanRefund> refund = meiTuanRsp.getRefund();
        logger.debug("coupon is : {}",coupon);
        logger.debug("order is : {}",order);
        logger.debug("refund is : {}",refund);

        if (!ListUtil.isEmptyList(coupon) || coupon.size() >= 1){
            logger.debug("coupon is not null");
            for (MeiTuanCoupon meiTuanCoupon : coupon) {
                if (meiTuanCoupon.getPrice().compareTo(order.getDirect()) == 0
                        && meiTuanCoupon.getOrderid().equals(order.getOrderid())) {
                    MeituanOrders orders = buildMeituanOrders(meiTuanCoupon, order);
                    handleMeiTuanOrders(orders);
                }
            }
        }

        if (!ListUtil.isEmptyList(refund) || refund.size() >= 1){
            logger.debug("refund orders is not null");
            for (MeiTuanRefund meiTuanRefund : refund) {
                MeituanRefundOrders refundOrders = buildMeituanRefundOrders(meiTuanRefund);
                handleRefundOrders(refundOrders);
            }
        }
    }

    public void handleMeiTuanOrders(MeituanOrders orders){
        logger.debug("orders is : {}",orders);
        MeituanOrders preOrders = meituanOrdersMapper.selectMeituanOrdersByOrderId(orders.getOrderId());
        if (preOrders != null){
            logger.debug("meituanOrders has inert");
            return;
        }

        User user = userMapper.selectById(Long.valueOf(orders.getSid()));
        logger.debug("handleMeiTuanOrders user is : {}",user);
        // 找不到用户直接入库
        if (user == null){
            logger.debug("user is null");
            orders.setIsRecord(0);
            addOrUpdateMeituanOrders(orders,preOrders);
            return;
        }

        // 计算用户佣金
        countCommission(orders.getProfit(),user,orders);

        // 保存或更新美团订单信息
        orders.setIsRecord(1);
        orders.setUserId(user.getUserId());
        orders.setUserName(user.getUserNickName());
        if (user.getParentUserId() != null){
            User parentUser = userMapper.selectById(user.getParentUserId());
            orders.setPromoterId(user.getParentUserId());
            orders.setPromoterName(parentUser.getUserNickName());
        }
        addOrUpdateMeituanOrders(orders,preOrders);

        // 创建用户收益记录 -- 美团订单不需要冻结佣金，11号统一结算上个月之前的订单
        createOrUpdateUserIncome(orders,user,preOrders);
    }

    public void handleRefundOrders(MeituanRefundOrders refundOrders){
        logger.debug("reundOrders is : {}",refundOrders);

        MeituanOrders orders = meituanOrdersMapper.selectMeituanOrdersByOrderId(refundOrders.getOrderId());
        logger.debug("handleMeiTuanOrders orders is : {}",orders);
        // 订单不存在不需要进行处理
        if (orders == null){
            return;
        }

        if (orders.getUserId() != null){
            refundOrders.setUserId(orders.getUserId());
        }
        // 创建或更新记录
        createOrUpdateRefundOrders(refundOrders);

        // 查询订单的收益记录
        List<UserIncome> userIncomeList = userIncomeMapper.selectUserIncomeByOrdersId(refundOrders.getOrderId());

        if (!ListUtil.isEmptyList(userIncomeList) || userIncomeList.size() > 0){
            for (UserIncome userIncome : userIncomeList) {
                long userId = userIncome.getUserId();
                BigDecimal money = userIncome.getMoney();
                long uit = money.multiply(new BigDecimal("100")).longValue();
                // 如果已经转账给用户，那么进行扣款
                if (userIncome.getStatus() == UserIncomeConstant.IS_PAID){
                    if(uit >0){
                        userMapper.plusUserUit(-uit,userId);
                    }
                }else{
                    // 将收益状态更改为已经付款
                    UserIncome nU = new UserIncome();
                    nU.setUserIncomeId(userIncome.getUserIncomeId());
                    nU.setStatus(UserIncomeConstant.IS_PAID);
                    userIncomeMapper.updateByPrimaryKeySelective(nU);
                }

                Integer type = UserIncomeConstant.MEITUAN_REFUND_ORDER_TYPE;
                Integer isPaid = UserIncomeConstant.IS_PAID;
                userIncome.setType(type);
                userIncome.setStatus(isPaid);
                userIncome.setMoney(money.negate());
                Date date = new Date();
                String format = sdf.format(date);
                userIncome.setCreateTime(format);
                userIncome.setUpdateTime(format);
                userIncome.setUserIncomeId(null);
                userIncomeMapper.insertSelective(userIncome);
            }
        }
    }

    private void createOrUpdateRefundOrders(MeituanRefundOrders refundOrders){
        MeituanRefundOrders refundOrdersDB = meituanRefundOrdersMapper.selectMeituanRefundOrders(refundOrders.getOrderId());
        if (refundOrdersDB == null){
            meituanRefundOrdersMapper.insertMeituanRefundOrders(refundOrders);
        }
    }

    private void createOrUpdateUserIncome(MeituanOrders meituanOrders,User user,MeituanOrders preOrders){
        logger.debug("meituanOrders is : {}",meituanOrders);
        logger.debug("user is : {}",user);
        logger.debug("preOrders is : {}",preOrders);

        if (preOrders == null){
            logger.debug("preOrders is null should insert userIncome");
            // 以前的订单不存在，直接创建收益记录
            createUserIncome(meituanOrders,user);
        }else{
            logger.debug("preOrders is not null should insert userIncome or update userIncome");
            List<UserIncome> userIncomeList = userIncomeMapper.selectUserIncomeByOrdersId(meituanOrders.getOrderId());
            if (ListUtil.isEmptyList(userIncomeList) || userIncomeList.size() < 1){
                // 以前的订单存在，但收益记录不存在，则进行创建
                createUserIncome(meituanOrders,user);
            }else{
                // 更新收益记录
                updateUserIncome(meituanOrders,user);
            }
        }

    }

    private void createUserIncome(MeituanOrders meituanOrders,User user){
        logger.debug("create meituan orders userIncome");
        UserIncome userIncome = UserIncomeBuilder.buildMeiTuanOrdersUserIncome(
                meituanOrders, meituanOrders.getUserUit(), user.getUserId(), 0);
        logger.debug("userIncome is : {}",userIncome);
        userIncomeMapper.insertSelective(userIncome);

        if (user.getParentUserId() != null){
            logger.debug("parentUserId is not null");
            UserIncome parentUserIncome = UserIncomeBuilder.buildMeiTuanOrdersUserIncome(
                    meituanOrders, meituanOrders.getOneLevelUserUit(), user.getParentUserId(), 1);
            logger.debug("parentUserIncome is : {}",userIncome);
            userIncomeMapper.insertSelective(parentUserIncome);
            User parentPUser = userMapper.selectById(user.getParentUserId());
            if (parentPUser != null){
                logger.debug("parentPUserId is not null");
                UserIncome parentPUserIncome = UserIncomeBuilder.buildMeiTuanOrdersUserIncome(
                        meituanOrders, meituanOrders.getTwoLevelUserUit(), parentPUser.getParentUserId(), 2);
                logger.debug("parentPUserIncome is : {}",userIncome);
                userIncomeMapper.insertSelective(parentPUserIncome);
            }
        }
    }

    private void updateUserIncome(MeituanOrders meituanOrders,User user){
        logger.debug("create meituan orders userIncome");
        UserIncome userIncome = UserIncomeBuilder.buildMeiTuanOrdersUserIncome(
                meituanOrders, meituanOrders.getOneLevelUserUit(), user.getUserId(), 0);
        logger.debug("userIncome is : {}",userIncome);
        userIncomeMapper.updateUserIncomeByUserIncome(userIncome);

        if (user.getParentUserId() != null){
            logger.debug("parentUserId is not null");
            UserIncome parentUserIncome = UserIncomeBuilder.buildMeiTuanOrdersUserIncome(
                    meituanOrders, meituanOrders.getTwoLevelUserUit(), user.getParentUserId(), 1);
            logger.debug("parentUserIncome is : {}",userIncome);
            userIncomeMapper.updateUserIncomeByUserIncome(parentUserIncome);
            User parentPUser = userMapper.selectById(user.getParentUserId());
            if (parentPUser != null){
                logger.debug("parentPUserId is not null");
                UserIncome parentPUserIncome = UserIncomeBuilder.buildMeiTuanOrdersUserIncome(
                        meituanOrders, meituanOrders.getTwoLevelUserUit(), parentPUser.getUserId(), 2);
                logger.debug("parentPUserIncome is : {}",userIncome);
                userIncomeMapper.updateUserIncomeByUserIncome(parentPUserIncome);
            }
        }

    }

    private void countCommission(BigDecimal profit,User user,MeituanOrders orders){
        logger.debug("profit is : {}",profit);
        Long userId = user.getUserId();
        Long parentUserId = null;
        Long parentPUserId = null;
        User parentUser;

        UserGrade userGrade = userGradeMapper.selectByPrimaryKey(user.getUserGradeId());
        Double firstLevelCommission = userGrade.getFirstCommission();
        Double secondLevelCommission = 0.00;
        Double thirdLevelCommission = 0.00;

        if (user.getParentUserId() != null){
            parentUserId = user.getParentUserId();
            parentUser = userMapper.selectById(parentUserId);
            UserGrade ug = userGradeMapper.selectByPrimaryKey(parentUser.getUserGradeId());
            secondLevelCommission = ug.getSecondCommission();

            if (parentUser.getParentUserId() != null){
                parentPUserId = parentUser.getParentUserId();
                User parentPUser = userMapper.selectById(parentUser.getParentUserId());
                logger.debug("parentPUser is : {}",parentPUser);
                UserGrade userGrade1 = userGradeMapper.selectByPrimaryKey(parentPUser.getUserGradeId());
                thirdLevelCommission = userGrade1.getThirdCommission();
            }
        }

        // 根据用户下单价格到佣金等级表进行查找
        List<CommissionLevelSettings> commissionLevelSettingses =
                commissionLevelSettingsMapper.selectByBeginAndEnd(profit);
        logger.debug("commissionLevelSettingses is : {}",commissionLevelSettingses);

        if(!ListUtil.isEmptyList(commissionLevelSettingses)){
            List<CommissionLevelSettings> st1 = commissionLevelSettingses.stream()
                    .filter(setting -> !userGrade.getId().equals(setting.getUserGradeId()))
                    .collect(Collectors.toList());
            logger.debug("st1 is : {}",st1);
            // 如果用户等级佣金比例设置开启
            if(userGrade.getEnableCmlevelSettings() == 1){
                List<CommissionLevelSettings> st2 = commissionLevelSettingses.stream()
                        .filter(setting -> userGrade.getId().equals(setting.getUserGradeId()))
                        .collect(Collectors.toList());
                logger.debug("st2 is : {}",st2);

                if(!ListUtil.isEmptyList(st2)){
                    st1 = st2;
                }
            }
            commissionLevelSettingses = st1;
        }

        // 如果佣金等级表存在多条适合条件记录（设置重叠情况），那么取第一条
        // 佣金等级表的佣金比例用户等级设置比率
        if (!ListUtil.isEmptyList(commissionLevelSettingses)){
            CommissionLevelSettings commissionLevelSettings = commissionLevelSettingses.get(0);
            firstLevelCommission = commissionLevelSettings.getRate().doubleValue();
        }

        logger.debug("one , two , three level commission rate is : {},{},{}",
                firstLevelCommission,secondLevelCommission,thirdLevelCommission);

        // 如果等级表的数据某一条为空,按照默认值设置
        firstLevelCommission = firstLevelCommission == null ? 100 : firstLevelCommission;
        secondLevelCommission = secondLevelCommission == null ? 0 : secondLevelCommission;
        thirdLevelCommission = thirdLevelCommission == null ? 0 : thirdLevelCommission;
        // 用户本人佣金
        BigDecimal userCommission =
                caculateCommission(profit,firstLevelCommission);
        // 上级佣金
        BigDecimal oneLevelCommission =
                caculateCommission(profit,secondLevelCommission);
        // 上上级佣金
        BigDecimal twoLevelCommission =
                caculateCommission(profit,thirdLevelCommission);
        // 用户佣金可以直接设置
        logger.debug("userCommission,oneLevelCommission,twoLevelCommission is : {},{},{}",
                userCommission,oneLevelCommission,twoLevelCommission);
        orders.setUserCommission(userCommission);
        // 计算用户获取的积分宝，上级积分宝，上上级积分宝
        Long userUit = DecimalUtil.convertMoneyToUit(userCommission);
        Long oneLevelUit = DecimalUtil.convertMoneyToUit(oneLevelCommission);
        Long twoLevelUit = DecimalUtil.convertMoneyToUit(twoLevelCommission);
        orders.setUserUit(userUit);

        if(parentUserId != null){
            orders.setOneLevelCommission(oneLevelCommission);
            orders.setOneLevelUserUit(oneLevelUit);
        }

        if(parentPUserId != null){
            orders.setTwoLevelCommission(twoLevelCommission);
            orders.setTwoLevelUserUit(twoLevelUit);
        }
        logger.debug("meituan orders userUit,oneLevelUit,twoLevelUit is : {},{},{}", userUit,oneLevelUit,twoLevelUit);
    }

    /**
     * 用BigDecimal 计算是避免精度丢失问题
     * @param totalGetMoney
     * @param commissionRate
     * @return
     */
    private BigDecimal caculateCommission(BigDecimal totalGetMoney, Double commissionRate){
        // 四舍五入
        BigDecimal bCimmissionRate = new BigDecimal(commissionRate)
                .setScale(OrdersConstant.SCALE,BigDecimal.ROUND_DOWN);
        // 除于100, 四舍五入
        bCimmissionRate = bCimmissionRate.divide(new BigDecimal("100"),BigDecimal.ROUND_DOWN)
                .setScale(OrdersConstant.SCALE,BigDecimal.ROUND_DOWN);
        // 乘于佣金比例等于用户所得佣金
        return totalGetMoney
                .multiply(bCimmissionRate)
                .setScale(OrdersConstant.SCALE,BigDecimal.ROUND_DOWN);
    }

    private void addOrUpdateMeituanOrders(MeituanOrders orders,MeituanOrders preOrders){
        logger.debug("preOrders is :{}",preOrders);

        if (preOrders == null){
            logger.debug("insert meituan orders");
            meituanOrdersMapper.insertSelective(orders);
        }else{
            logger.debug("update meituan orders");
            meituanOrdersMapper.updateMeituanOrders(orders);
        }
    }

    private MeituanOrders buildMeituanOrders(MeiTuanCoupon meiTuanCoupon,MeiTuanOrderRsp order){
        MeituanOrders orders = new MeituanOrders();
        orders.setOrderId(order.getOrderid());
        orders.setDirect(order.getDirect());
        orders.setTotal(order.getTotal());
        orders.setNewBuyer(meiTuanCoupon.getNewbuyer());
        orders.setQuantity(order.getQuantity());
        orders.setPrice(meiTuanCoupon.getPrice());
        orders.setProfit(meiTuanCoupon.getProfit());
        orders.setSequence(meiTuanCoupon.getSequence());
        orders.setUid(order.getUid());
        orders.setSign(order.getSign());
        orders.setSmsTitle(order.getSmstitle());
        orders.setSid(order.getSid());
        if (order.getPaytime() != null) {
            Long payTime = order.getPaytime()*1000;
            String format = sdf.format(payTime);
            orders.setPayTime(format);
        }
        if (meiTuanCoupon.getUsetime() != null) {
            Long useTime = meiTuanCoupon.getUsetime()*1000;
            String format = sdf.format(useTime);
            orders.setUseTime(format);
        }
        if (order.getModtime() != null){
            Long modTime = order.getModtime()*1000;
            String format = sdf.format(modTime);
            orders.setModtime(format);
        }
        return orders;
    }

    private MeituanRefundOrders buildMeituanRefundOrders(MeiTuanRefund meiTuanRefund){
        MeituanRefundOrders refundOrders = new MeituanRefundOrders();
        refundOrders.setMoney(meiTuanRefund.getMoney());
        refundOrders.setOrderId(meiTuanRefund.getOrderid());
        refundOrders.setProfit(meiTuanRefund.getProfit());
        Date date = new Date();
        refundOrders.setCreateTime(date);
        refundOrders.setUpdateTime(date);
        if (meiTuanRefund.getRefundtime() != null){
            Long refundTime = meiTuanRefund.getRefundtime()*1000;
            String format = sdf.format(refundTime);
            refundOrders.setRefundTime(format);
        }
        return refundOrders;
    }
}
